home *** CD-ROM | disk | FTP | other *** search
/ Cracking 2 / Cracking II..iso / Texty / crackme / PACME-~1.TXT < prev    next >
Encoding:
Text File  |  1999-07-25  |  14.8 KB  |  312 lines

  1.                      solution for Kwazy Webbit's PacMe Crackme          
  2.                            solved By Nuno1 on 24 july 1999              
  3.                   any comments can be sent to nuno_2@hotmail.com       
  4.  
  5.  
  6. Information :
  7.     Cracker    : Nuno1 
  8.     Date       : 24 july 1999
  9.     Level      : 4
  10.     Protection : KeyFile Missing , Simple Encryption Method.
  11.  
  12.     Tools used :
  13.       - SoftIce
  14.       - Borland C for Keyfile Generator.
  15.  
  16. Hey Crackers !
  17.  
  18. this is one of the cracks i really enjoy cracking. not an easy one but really not hard one.
  19.  
  20. -- Information --
  21.  
  22. when you run the program , you see an UNREGISTERD label , and also a CHECK Button.
  23. you cant write on the UNREGISTERD label . just a check button left ;)
  24.  
  25. -- The Crack --
  26.  
  27. because of it , you can understand that its not a serial / code crack .
  28. let see if its a KeyFile crack .. 
  29.  
  30. bpx on CreateFileA to break if a file is open .
  31.  
  32. press the check button .. yep .. it jump to the trap .. ;)
  33.  
  34. CreateFileA function gets on EDX the name of the file .
  35. lets do "d edx" .. you can see a strange filename called "KwazyWeb.bit" .
  36. ok ... copy your autoexec.bat to this directory and rename it KwazyWeb.bit.
  37. lets press the check button again ..
  38. ok .. now press F12 and u will see Eax return a number (if it was -1 it means not exists)
  39. so we made the first step ..
  40. lets contine .. you will see this code :
  41.  
  42. :004016D9 E81C010000              KERNEL32.CreateFileA             
  43. :004016DE 83F8FF                  cmp eax, FFFFFFFF        <- check if the KwazyWeb.bit exist
  44. :004016E1 7464                    je 00401747
  45. :004016E3 A344344000              mov dword ptr [00403444], eax    <-moving the handle of the file
  46. :004016E8 6A00                    push 00000000 
  47. :004016EA 6848344000              push 00403448                <-pushing a variable
  48. :004016EF 6A01                    push 00000001                <-pushing 1
  49. :004016F1 68FA344000              push 004034FA                <-pushing another variable. 
  50. :004016F6 FF3544344000            push dword ptr [00403444]    <-and the handle of the file
  51. :004016FC E811010000              KERNEL32.ReadFile            <-call the readfile.
  52.  
  53. ok , whats really going on here.
  54.  
  55. the ReadFile function get some params .. all we really cares are the PUSH 00000001 and 
  56. PUSH 004034FA .. the PUSH 1 is really the length to read from the file.
  57. the push 4034fa is where to copy the read chars..
  58.  
  59. ok , so he read one byte to 4034fa.
  60. look at 4034fa after Readfile you will notice the first char that in your file.
  61.  
  62. lets contine :
  63.  
  64. :00401701 0FB605FA344000          movzx eax, byte ptr [004034FA]  <- eax get the first char
  65. :00401708 85C0                    test eax, eax                   <- check if it 0
  66. :0040170A 743B                    je 00401747              
  67. :0040170C 6A00                    push 00000000                   
  68. :0040170E 6848344000              push 00403448
  69. :00401713 50                      push eax                        <- push the first char
  70. :00401714 6888324000              push 00403288                   <- another variable
  71. :00401719 FF3544344000            push dword ptr [00403444]       <- the handle of the file.
  72. :0040171F E8EE000000              KERNEL32.ReadFile               <- calling ReadFile
  73.  
  74. ok .. so now he called readfile again but this time he used the first char as the new
  75. length to read .. is it a len of any string ? maybe but we dont care yet ;).
  76.  
  77. after that there is a call .. let see what is this call :
  78.  
  79. :00401000 33C0                    xor eax, eax                  <- eax = 0
  80. :00401002 33D2                    xor edx, edx                  <- edx = 0
  81. :00401004 33C9                    xor ecx, ecx                  <- ecx = 0
  82. :00401006 8A0DFA344000            mov cl, byte ptr [004034FA]   <- cl = length
  83. :0040100C BE88324000              mov esi, 00403288             <- esi = the new chars we read
  84. :00401011 AC                      lodsb                         <- read a char from esi and
  85.                                                                 <- and esi + 1
  86. :00401012 03D0                    add edx, eax                  <- edx + char
  87. :00401014 E2FB                    loop 00401011                 <- loop length times
  88. :00401016 8815FB344000            mov byte ptr [004034FB], dl   <- take the low byte of dx and
  89.                                     <- keep it in 4034fb
  90. :0040101C C3                      ret
  91.  
  92. as we can understand .. this is just calculate the sum of the characters we read and keep
  93. it in a variable (4034fb)
  94.  
  95. lets return to after the call :
  96.  
  97. :00401729 6A00                    push 00000000       
  98. :0040172B 6848344000              push 00403448
  99. :00401730 6A12                    push 00000012               <- push 12
  100. :00401732 68E8344000              push 004034E8               <- push it
  101. :00401737 FF3544344000            push dword ptr [00403444]   <- push our file handle
  102. :0040173D E8D0000000              Call KERNEL32.ReadFile      <- readfile 
  103. :00401742 E882F9FFFF              call 004010C9               <- ??
  104. :00401747 FF3544344000            push dword ptr [00403444]   <- file handle
  105. :0040174D E8A2000000              Call KERNEL32.CloseHandle   <- closefile
  106.  
  107. so we see now that it push 12h as the length param , so he take 12h next characters.
  108. after the strange call he close the file .. so maybe all the answers is in this call.
  109.  
  110. let check it out :
  111.  
  112. :004010C9 55                      push ebp
  113. :004010CA 8BEC                    mov ebp, esp
  114. :004010CC 83C4FC                  add esp, FFFFFFFC
  115. :004010CF 6865334000              push 00403365  <- looks like a strange looking maze !?
  116. :004010D4 68BC314000              push 004031BC  <- this is the same as above !
  117. :004010D9 E83A070000              Call KERNEL32.lstrcpyA    <- copy to 403365 the 4031bc string
  118. :004010DE C70584314000CC314000    mov dword ptr [00403184], 004031CC 
  119. :004010E8 E830FFFFFF              call 0040101D    <-another call !          
  120.  
  121.  
  122. so he copy a strange looking maze and then calling another function .. let see what is this function
  123.  
  124. :0040101D 8A15FB344000            mov dl, byte ptr [004034FB]  <- the total we calculate before
  125. :00401023 B912000000              mov ecx, 00000012            <- ecx = 12 ?
  126. :00401028 B8E8344000              mov eax, 004034E8            <- eax = 12 characters we read
  127. :0040102D 3010                    xor byte ptr [eax], dl       <- xor the new characters we read
  128.                                    <- with the lowbyte of the total we calc.
  129. :0040102F 40                      inc eax                      <- go to the next char.
  130. :00401030 E2FB                    loop 0040102D                <- loop 12h times.
  131. :00401032 C3                      ret
  132.  
  133. mmmm .. so now we can see he take the 12 numbers we read last and xor it with the lowbyte
  134. total of characters we read before.
  135.  
  136.  
  137. let see now whats happend (returning from the call);
  138.  
  139.  
  140. :004010ED C645FE00                mov [ebp-02], 00              <-ebp-2 = 0
  141. :004010F1 33C0                    xor eax, eax                  <-eax=0
  142. :004010F3 33C9                    xor ecx, ecx                  <-ecx=0
  143. :004010F5 C645FF08                mov [ebp-01], 08              <-ebp-1 = 8
  144. :004010F9 806DFF02                sub byte ptr [ebp-01], 02     <-ebp-1 - 2
  145. :004010FD 0FB64DFE                movzx ecx, byte ptr [ebp-02]  <-ecx = ebp-2 
  146. :00401101 81C1E8344000            add ecx, 004034E8             <-ecx=ecx + the start of the xored numbers
  147. :00401107 8A01                    mov al, byte ptr [ecx]        <-al = xored number   
  148. :00401109 8A4DFF                  mov cl, byte ptr [ebp-01]     <-cl = ebp -1
  149. :0040110C D2E8                    shr al, cl                    <-al >> cl ???
  150. :0040110E 2403                    and al, 03                    <-al & 3 (11b)
  151. :00401110 E81EFFFFFF              call 00401033                 <-another call
  152. :00401115 85C0                    test eax, eax                 <-eax = 0 ? jmp
  153. :00401117 7411                    je 0040112A
  154. :00401119 0FB655FF                movzx edx, byte ptr [ebp-01]  <-edx = ebp-1
  155. :0040111D 85D2                    test edx, edx                 <-edx = 0 ?
  156. :0040111F 75D8                    jne 004010F9                  <-if not jmp
  157. :00401121 FE45FE                  inc [ebp-02]                  <-if yes, inc ebp2
  158. :00401124 807DFE12                cmp byte ptr [ebp-02], 12     <-ebp-2 <> 12 ??
  159. :00401128 75CB                    jne 004010F5                  <-then jump
  160. :0040112A C9                      leave                         <-else finish
  161. :0040112B C3                      ret
  162.  
  163. ok , lets start to make it understanding (even before the call we didnt yet examine.
  164. ebp-2 looks like a counter of 12h because it been increased every time and exit when = 12
  165. ebp-1 = 6 at start (notice the first sub of it with 2) and allways dec by 2 and it also a
  166.       counter , because it test when it 0 .
  167. so we first can understand this is loop in a loop.
  168. we call the first loop outloop and the second loop inloop.
  169.  
  170. in the inloop he takes one xored number shl it with 6 and keep the two first bits and then
  171. the same with with 4 , 2 and 0. then he exit the loop. the outloop go increase ECX and
  172. thats make the inloop get the next xored number. all this goes until the outloop pass 12h
  173. times.
  174.  
  175. in other words :
  176.  
  177. every number from the xored numbers are 4 numbers that are from 0 to 3 (00b,01b,10b and 11b)
  178. each two bits in the byte represent a number from 0-3.
  179. so this is 04h * 12h numbers to pass.
  180.  
  181. now.. let see what the other call do .. 
  182.  
  183. :00401033 55                      push ebp
  184. :00401034 8BEC                    mov ebp, esp
  185. :00401036 83C4F8                  add esp, FFFFFFF8
  186. :00401039 8B1584314000            mov edx, dword ptr [00403184] <- edx = the place on the MAZE
  187.                                     <- that the char "C" found
  188. :0040103F 8955FC                  mov dword ptr [ebp-04], edx   <-ebp-4 = "C" char
  189. :00401042 0AC0                    or al, al                     <- or al,al
  190. :00401044 7509                    jne 0040104F                  <- jmp if al <> 0
  191. :00401046 832D8431400010          sub dword ptr [00403184], 00000010 <-if 0 add to the pointer
  192.                                                                      <-"C" place 10
  193. :0040104D EB1F                    jmp 0040106E                  <- jmp 40106e
  194. :0040104F 3C01                    cmp al, 01                    <- if al = 1
  195. :00401051 7508                    jne 0040105B                  <- if not go to 40105b
  196. :00401053 FF0584314000            inc dword ptr [00403184]      <-  add to the pointer of "C" 1
  197. :00401059 EB13                    jmp 0040106E                  <- jmp 40106e
  198. :0040105B 3C02                    cmp al, 02                    <- al,2
  199. :0040105D 7509                    jne 00401068                  <- if not go to 401068
  200. :0040105F 83058431400010          add dword ptr [00403184], 00000010 <- add to the ptr of "C" 10
  201. :00401066 EB06                    jmp 0040106E                  <- jmp 
  202. :00401068 FF0D84314000            dec dword ptr [00403184]      <- if not 0,1,2 (means 3) 
  203.                                             <- subthe ptr of "C" 1
  204. :0040106E 8B1584314000            mov edx, dword ptr [00403184] <- here all the jmp come to.
  205.                                 <- edx = new MAZE place
  206. :00401074 8A02                    mov al, byte ptr [edx]        <- al = MAZE
  207. :00401076 3C2A                    cmp al, 2A                    <- al = '*'
  208. :00401078 7506                    jne 00401080                  <- if not jmp
  209. :0040107A 33C0                    xor eax, eax                  <- if yes eax=0
  210. :0040107C C9                      leave                         <- and leave
  211. :0040107D C3                      ret
  212. :0040107E EB33                    jmp 004010B3
  213. :00401080 3C58                    cmp al, 58                    <- if not "*" is it "X"
  214. :00401082 752F                    jne 004010B3                       
  215.  
  216. i will cut if it IS 58 and jump to if its not 58.
  217.  
  218. :004010B3 8B1584314000            mov edx, dword ptr [00403184] <- edx = maze place.
  219. :004010B9 C60243                  mov byte ptr [edx], 43        <- maze place = "C"
  220. :004010BC 8B55FC                  mov edx, dword ptr [ebp-04]   <- old maze place
  221. :004010BF C60220                  mov byte ptr [edx], 20        <- maze = " "
  222. :004010C2 B801000000              mov eax, 00000001             <- eax = 1 and exit.
  223. :004010C7 C9                      leave
  224. :004010C8 C3                      ret
  225.  
  226. ok .. lets start to understand this maze thing
  227.  
  228. if you will look at EDX whe it get [403184] you will see this maze :
  229.  
  230. ****************
  231. C*      *   ****
  232.  * ****   *    *
  233.  *  ********** *
  234.   *    *   *   *
  235. * **** * *   ***
  236. * *    * *******
  237.   * ***  *     *
  238.  *  *** ** *** *
  239.    ****    *X  *
  240. ****************
  241.  
  242. you can notice the C and X letters . the place we get into start in the C char.
  243.  
  244. you can count , the number of * at the first line are 16 (10h) .
  245.  
  246. ok now let see what the function does really.
  247.  
  248. all it does is check if the number he got is 0,1,2,3.
  249. if 0 , he sub 10h from the maze place that will bring us in the same X-coord in the maze
  250. but one line up (in the Y-Coord). 
  251. if 1 , he increase the maze place.. it means we moved left. 
  252. so every number really get us to a diffrent position.. (0,1,2,3 is the number of postions !)
  253.  
  254. so here is the moves :
  255. 0 - up
  256. 1 - right
  257. 2 - down
  258. 3 - left
  259.  
  260. ok so he place it in the new place and check if there is a "*" in it .. 
  261. if there is , he return to the called fuction 0. if its not he return 1.
  262. if its 'X' he jump to a place that said SUCCESS .... ha ! thats it ..
  263. we finish debugging it ... but what now ? what we need to do ?
  264.  
  265. ok ... here it goes .
  266.  
  267. as we now know the 12h numbers we pass are really a 12h * 4h moves of the maze .
  268. (you can check the numbers of moves in it you will notice its right ;) ).
  269. but the problem is that we cant just write the numbers in the file and let him read it
  270. because its xored with the total characters we read before ... and now we can also notice
  271. those characters are the registration Name !! 
  272. so he XORED those 12h number with the total sum of the Registration Name !!
  273.  
  274. this method is really called xored encyption , if you have the xored key you just have to
  275. xor the number with the key and you get the same number !
  276.  
  277. so all we have to do (as i allready did) is to write a program that sum Registration name 
  278. and have a table with all the steps we need to do , and start to xor it with the sum.
  279. keep all of this in the file and it will be cracked ;)
  280.  
  281. as you can see , this is the maze soulotion (but with the real numbers for the move)
  282.  
  283. C 011111 011
  284. 2 0    211 2111
  285. 2 10          2
  286. 21 3330 330 332
  287.  2    0 2 332
  288.  2 0111 2
  289. 32 0   32 01111 
  290. 2 01   2  0   2 
  291. 211    2111 332 
  292.  
  293. and in a better way to view it :
  294. 22212223221101
  295. 00111003330100
  296. 11111211011211
  297. 12233233033222
  298. 32211100111122
  299. 33
  300.  
  301. just xor this with the total and you finished .. you are welcome to look at my source code.
  302.  
  303. -- Notes --
  304.  
  305. this was a fun crackme for me ... i hope there are more nice crackme like that ;)
  306.  
  307. hope you learn somthing new ;)
  308.  
  309. Nuno1 - Nuno2@hotmail.com
  310.  
  311.  
  312.